package com.frejoys.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.frejoys.common.dto.agent.AgentRoleGroupPageDto;
import com.frejoys.common.dto.agent.AgentRoleGroupSaveDto;
import com.frejoys.common.dto.agent.AgentRoleGroupUpdateDto;
import com.frejoys.common.dto.common.IdDto;
import com.frejoys.common.enums.EStatus;
import com.frejoys.common.enums.EUserRole;
import com.frejoys.common.error.HttpStatus;
import com.frejoys.common.exception.GeneralException;
import com.frejoys.common.util.CommonUtil;
import com.frejoys.common.util.TimeUtil;
import com.frejoys.common.vo.ad.AdPageVo;
import com.frejoys.common.vo.agent.AgentRoleGroupVo;
import com.frejoys.common.vo.agent.AgentUserInfoVo;
import com.frejoys.common.vo.agent.AgentUserVo;
import com.frejoys.dao.entity.*;
import com.frejoys.dao.mapper.*;
import com.frejoys.service.AgentRoleGroupRatioService;
import com.frejoys.service.AgentRoleGroupService;
import com.frejoys.service.UserLevelAgentService;
import com.frejoys.service.UserLevelPromotionService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author wangzhicheng
 * @version 1.0
 * @date 2024/4/25 10:00
 */
@Service
@RequiredArgsConstructor
public class AgentRoleGroupServiceImpl extends ServiceImpl<AgentRoleGroupMapper, AgentRoleGroup> implements AgentRoleGroupService {

    private final AgentRoleMapper agentRoleMapper;

    private final PlatformWalletMapper platformWalletMapper;

    private final AgentUserMapper agentUserMapper;

    private final UserMapper userMapper;

    private final UserLevelAgentService userLevelAgentService;

    private final UserLevelPromotionService userLevelPromotionService;

    private final AgentRoleGroupRatioMapper agentRoleGroupRatioMapper;

    @Override
    public AgentRoleGroup getRebateListById(Integer id) {
        LambdaQueryWrapper<AgentRoleGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AgentRoleGroup::getId, AgentRoleGroup::getPid, AgentRoleGroup::getPath, AgentRoleGroup::getUserId, AgentRoleGroup::getRebateRatio).eq(AgentRoleGroup::getId, id);
        return getOnly(wrapper);
    }

    @Override
    public List<AgentRoleGroup> getRebateListById(List<Integer> id) {
        LambdaQueryWrapper<AgentRoleGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AgentRoleGroup::getId, AgentRoleGroup::getPid, AgentRoleGroup::getPath, AgentRoleGroup::getUserId, AgentRoleGroup::getRebateRatio).in(AgentRoleGroup::getId, id).orderByAsc(AgentRoleGroup::getPath);
        return list(wrapper);
    }

    @Override
    public AgentRoleGroup getTopInfo(List<AgentRoleGroup> list) {
        for (AgentRoleGroup e : list) {
            if (e.getPid().equals(EStatus.off.getValue())) {
                return e;
            }
        }
        return null;
    }

    /**
     * 后台设置代理角色组
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAgentRoleGroup(AgentRoleGroupSaveDto dto) {
//        if (validateARole(dto.getName(), null)) {
//            //代理角色组已存在
//            throw new GeneralException(HttpStatus.agentRoleGroupExist);
//        }

        AgentRoleGroup roleGroup = new AgentRoleGroup();

        //查询出上级层级
        AgentRoleGroup agentRoleGroup = baseMapper.getPidPath(dto.getPid());

        BeanUtils.copyProperties(dto, roleGroup);
        roleGroup.setPath(ObjectUtil.isEmpty(agentRoleGroup) ? "0" : CommonUtil.getPath(agentRoleGroup.getId(), agentRoleGroup.getPath()));
        roleGroup.setCreateTime(TimeUtil.unixTime());

        Float totalRatio = 0f;
        //校验比例
        if (dto.getPid() == 0) {

            totalRatio = dto.getRebateRatio() + dto.getAgentUserRatio() + dto.getAgentUserRatioOne() + dto.getAgentUserRatioTwo();

        } else {

            List<String> path = Arrays.asList(roleGroup.getPath().split(","));
            Integer id = Integer.valueOf(path.get(1));

            LambdaQueryWrapper<AgentRoleGroup> queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.select(AgentRoleGroup::getId, AgentRoleGroup::getRebateRatio)
                    .apply("FIND_IN_SET('" + id + "', path)")
                    .or().eq(AgentRoleGroup::getId, id);
            List<AgentRoleGroup> agentRoleGroups = baseMapper.selectList(queryWrapper);
            Map<Integer, Float> map = agentRoleGroups.stream().collect(Collectors.toMap(AgentRoleGroup::getId, AgentRoleGroup::getRebateRatio));

            LambdaQueryWrapper<AgentRoleGroupRatio> agentRoleGroupRatioWrapper = new LambdaQueryWrapper<>();
            agentRoleGroupRatioWrapper.eq(AgentRoleGroupRatio::getAgentRoleGroupId, id);
            AgentRoleGroupRatio agentRoleGroupRatio = agentRoleGroupRatioMapper.selectOne(agentRoleGroupRatioWrapper);

            if (ObjectUtil.isNotEmpty(agentRoleGroupRatio)) {
                totalRatio = agentRoleGroupRatio.getAgentUserRatio() + agentRoleGroupRatio.getAgentUserRatioOne() + agentRoleGroupRatio.getAgentUserRatioTwo();
            }

            for (String groupsId:path) {
                if (map.containsKey(Integer.valueOf(groupsId))){
                    totalRatio = totalRatio + map.get(Integer.valueOf(groupsId));
                }
            }

            totalRatio = totalRatio + dto.getRebateRatio();
        }

        if (totalRatio < 0 || totalRatio > 100) {
            throw new GeneralException(HttpStatus.ratioError);
        }

        //新增组
        save(roleGroup);

        //新增组钱包
        insertWallet(dto.getPid(), roleGroup.getId());

        //插入平台代理提成组提成信息
        if (dto.getPid() == 0) {
            AgentRoleGroupRatio agentRoleGroupRatio = new AgentRoleGroupRatio();
            agentRoleGroupRatio.setAgentRoleGroupId(roleGroup.getId());
            agentRoleGroupRatio.setAgentUserRatio(dto.getAgentUserRatio());
            agentRoleGroupRatio.setCommissionRatio(dto.getCommissionRatio());
            agentRoleGroupRatio.setPlatformRatio(dto.getPlatformRatio());
            agentRoleGroupRatio.setAgentUserRatioOne(dto.getAgentUserRatioOne());
            agentRoleGroupRatio.setAgentUserRatioTwo(dto.getAgentUserRatioTwo());
            agentRoleGroupRatioMapper.insert(agentRoleGroupRatio);
        }

        return true;
    }

    /**
     * 后台修改代理角色组名称和管理
     *
     * @param dto
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAgentGroup(AgentRoleGroupUpdateDto dto) {
//        if (validateARole(dto.getName(), dto.getId())) {
//            //代理角色组已存在
//            throw new GeneralException(HttpStatus.agentRoleGroupExist);
//        }
        LambdaQueryWrapper<AgentRoleGroup> agentRoleGroupWrapper = new LambdaQueryWrapper<>();
        agentRoleGroupWrapper.select(AgentRoleGroup::getId, AgentRoleGroup::getPid, AgentRoleGroup::getPath)
                .eq(AgentRoleGroup::getId, dto.getId());
        AgentRoleGroup agentRoleGroup = getOnly(agentRoleGroupWrapper);

        if (ObjectUtil.isNotEmpty(agentRoleGroup)) {

            //userid不等于空的时候是修改组长信息
            if (dto.getUserId() == null) {
                Float totalRatio = 0f;
                //校验比例
                Integer id = 0;
                if (agentRoleGroup.getPid() == 0) {
                    id = dto.getId();
                } else {
                    List<String> path = Arrays.asList(agentRoleGroup.getPath().split(","));
                    id = Integer.valueOf(path.get(1));
                }
                //查询代理组
                LambdaQueryWrapper<AgentRoleGroup> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.select(AgentRoleGroup::getId, AgentRoleGroup::getRebateRatio, AgentRoleGroup::getPath)
                        .apply("FIND_IN_SET('" + id + "', path)")
                        .or().eq(AgentRoleGroup::getId, id);
                List<AgentRoleGroup> agentRoleGroups = baseMapper.selectList(queryWrapper);
                Map<Integer, Float> map = agentRoleGroups.stream().collect(Collectors.toMap(AgentRoleGroup::getId, AgentRoleGroup::getRebateRatio));

                //组提成信息
                LambdaQueryWrapper<AgentRoleGroupRatio> agentRoleGroupRatioWrapper = new LambdaQueryWrapper<>();
                agentRoleGroupRatioWrapper.eq(AgentRoleGroupRatio::getAgentRoleGroupId, id);
                AgentRoleGroupRatio agentRoleGroupRatio = agentRoleGroupRatioMapper.selectOne(agentRoleGroupRatioWrapper);

                if (ObjectUtil.isNotEmpty(agentRoleGroupRatio) && dto.getAgentUserRatio() == null && dto.getAgentUserRatioOne() == null && dto.getAgentUserRatioTwo() == null) {
                    totalRatio = agentRoleGroupRatio.getAgentUserRatio() + agentRoleGroupRatio.getAgentUserRatioOne() + agentRoleGroupRatio.getAgentUserRatioTwo();
                } else {
                    totalRatio = dto.getAgentUserRatio() + dto.getAgentUserRatioOne() + dto.getAgentUserRatioTwo();
                }

                if (!agentRoleGroups.isEmpty()) {
                    for (AgentRoleGroup group : agentRoleGroups) {

                        Float ratio = 0f;

                        List<String> list = Arrays.asList(group.getPath().split(","));
                        if (list.contains(dto.getId().toString()) || group.getId() == dto.getId()) {
                            ratio = ratio + dto.getRebateRatio();
                        }
                        if (group.getId() != dto.getId()){
                            ratio = ratio + group.getRebateRatio();
                        }

                        for (String groupId : list) {
                            if (map.containsKey(Integer.valueOf(groupId)) && Integer.valueOf(groupId) != dto.getId()) {
                                ratio = ratio + map.get(Integer.valueOf(groupId));
                            }
                        }

                        ratio = ratio + totalRatio;

                        if (ratio < 0 || ratio > 100) {
                            throw new GeneralException(HttpStatus.ratioError);
                        }
                    }
                }
            }


            LambdaUpdateWrapper<AgentRoleGroup> wrapper = Wrappers.lambdaUpdate();
            wrapper.eq(AgentRoleGroup::getId, dto.getId());
            if (StrUtil.isNotEmpty(dto.getName())) {
                wrapper.set(AgentRoleGroup::getName, dto.getName());
            }

            if (ObjectUtil.isNotEmpty(dto.getUserId())) {
//            validateUserId(dto.getId(),dto.getUserId());
                wrapper.set(AgentRoleGroup::getUserId, dto.getUserId());

            }
            if (ObjectUtil.isNotEmpty(dto.getRebateRatio())) {
                wrapper.set(AgentRoleGroup::getRebateRatio, dto.getRebateRatio());
            }
            //修改组
            update(wrapper);

            //修改组提成信息
            if (agentRoleGroup.getPid() == 0 && dto.getUserId() == null) {

                LambdaUpdateWrapper<AgentRoleGroupRatio> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.eq(AgentRoleGroupRatio::getAgentRoleGroupId, dto.getId());

                if (dto.getCommissionRatio() != null) {
                    updateWrapper.set(AgentRoleGroupRatio::getCommissionRatio, dto.getCommissionRatio());
                }
                if (dto.getAgentUserRatio() != null) {
                    updateWrapper.set(AgentRoleGroupRatio::getAgentUserRatio, dto.getAgentUserRatio());
                }
                if (dto.getAgentUserRatioOne() != null) {
                    updateWrapper.set(AgentRoleGroupRatio::getAgentUserRatioOne, dto.getAgentUserRatioOne());
                }
                if (dto.getAgentUserRatioTwo() != null) {
                    updateWrapper.set(AgentRoleGroupRatio::getAgentUserRatioTwo, dto.getAgentUserRatioTwo());
                }
                if (dto.getPlatformRatio() != null) {
                    updateWrapper.set(AgentRoleGroupRatio::getPlatformRatio, dto.getPlatformRatio());
                }
                agentRoleGroupRatioMapper.update(updateWrapper);
            }
        }
        return true;
    }

    /**
     * 后台查询代理角色
     */
    @Override
    public IPage<AgentRoleGroupVo> searchAgentRoleGroupList(AgentRoleGroupPageDto dto) {

        Page<AgentRoleGroup> page = new Page<>(dto.getPage(), dto.getSize());


        //分页查出父级组
        Page<AgentRoleGroupVo> agentRoleGroupVoPage = baseMapper.pageAgentRoleGroup(page, dto);
        List<AgentRoleGroupVo> list = agentRoleGroupVoPage.getRecords();

        if (!list.isEmpty()) {
            setChild(list);
        }
        return agentRoleGroupVoPage;

    }

    /**
     * 用户查询自己管理的角色组信息
     *
     * @param userId
     */
//    @Override
//    public List<AgentRoleGroupVo> listAgentRoleGroupByUserId(Long userId) {
//        List<AgentRoleGroupVo> list = baseMapper.listAgentRoleGroupByUserId(userId);
//        if (!list.isEmpty()) {
//            //得到所有代理组id集合
//            List<Integer> agentGroupIds = list.stream().map(AgentRoleGroupVo::getId).toList();
//            //获取代理组用户
//            List<AgentUserVo> userVos = agentUserMapper.getUserInfo(agentGroupIds);
//            //筛选出第一级
//            List<AgentRoleGroupVo> firstGroup = list.stream().filter(r -> "0".equals(r.getPath())).toList();
//
//            return setChild(firstGroup);
//        }
//        return Collections.emptyList();
//    }

    /**
     * 查询自己推广的用户
     *
     * @param userId 登录人id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public List<AgentUserInfoVo> listAgentUserById(Long userId) {
        User user = userMapper.getSimpleUser(userId);
        if (ObjectUtil.isEmpty(user)) {
            throw new GeneralException(HttpStatus.userNoExist);
        }

        if (user.getStatus() < EStatus.on.getValue()) {
            throw new GeneralException(HttpStatus.userStatusLoginError);
        }

        if (CommonUtil.bitExistOffset(user.getRole(), EUserRole.promotion.getValue())) {
            return userLevelPromotionService.getPromotionUser(userId);
        }

        if (CommonUtil.bitExistOffset(user.getRole(), EUserRole.agent.getValue())) {
            return userLevelAgentService.getAgentUser(userId);
        }

        return Collections.emptyList();
    }


    @Override
    public boolean deleteAgentRoleGroup(IdDto dto) {

        LambdaQueryWrapper<AgentRoleGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AgentRoleGroup::getId)
                .eq(AgentRoleGroup::getPid, dto.getId());
//                .apply("FIND_IN_SET('" + dto.getId() + "', path)");
        List<AgentRoleGroup> agentRoleGroupList = baseMapper.selectList(queryWrapper);

        //判断组下面是否存在小组
        if (!agentRoleGroupList.isEmpty()) {
            throw new GeneralException(HttpStatus.existAgentRoleGroupError);
        }

        LambdaQueryWrapper<AgentUser> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AgentUser::getId)
                .eq(AgentUser::getAgentRoleGroupId, dto.getId());
        List<AgentUser> list = agentUserMapper.selectList(wrapper);

        //判断组下面是否存在职员
        if (!list.isEmpty()) {
            throw new GeneralException(HttpStatus.existAgentUserIdError);
        }

        LambdaQueryWrapper<AgentRoleGroup> agentRoleGroupWrapper = new LambdaQueryWrapper<>();
        agentRoleGroupWrapper.select(AgentRoleGroup::getPid).eq(AgentRoleGroup::getId, dto.getId());
        AgentRoleGroup agentRoleGroup = getOnly(agentRoleGroupWrapper);

        if (agentRoleGroup != null && agentRoleGroup.getPid() == 0) {
            //删除组提成信息
            LambdaQueryWrapper<AgentRoleGroupRatio> agentWrapper = new LambdaQueryWrapper<>();
            agentWrapper.eq(AgentRoleGroupRatio::getAgentRoleGroupId, dto.getId());
            agentRoleGroupRatioMapper.delete(agentWrapper);
        }

        //删除组
        baseMapper.deleteById(dto.getId());

        return true;
    }

    /**
     * 验重
     *
     * @param name
     * @param id
     */
//    private boolean validateARole(String name, Integer id) {
//        LambdaQueryWrapper<AgentRoleGroup> wrapper = Wrappers.lambdaQuery();
//        wrapper.select(AgentRoleGroup::getId).eq(AgentRoleGroup::getName, name);
//        if (ObjectUtil.isNotEmpty(id)) {
//            wrapper.ne(AgentRoleGroup::getId, id);
//        }
//        return ObjectUtil.isNotEmpty(getOnly(wrapper));
//    }

    //校验组长是否已被添加
    private boolean validateUserId(Integer agentRoleGroupId, Long userId) {
        LambdaQueryWrapper<AgentRoleGroup> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(AgentRoleGroup::getPath, AgentRoleGroup::getPid)
                .eq(AgentRoleGroup::getId, agentRoleGroupId);
        AgentRoleGroup agentRoleGroup = getOnly(queryWrapper);

        Integer id = 0;
        if (agentRoleGroup.getPid() == 0) {
            id = agentRoleGroupId;
        } else {
            List<String> path = Arrays.asList(agentRoleGroup.getPath().split(","));
            id = Integer.valueOf(path.get(1));
        }
        LambdaQueryWrapper<AgentRoleGroup> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(AgentRoleGroup::getId)
                .eq(AgentRoleGroup::getUserId, userId)
                .apply("FIND_IN_SET('" + id + "', path)")
                .or().eq(AgentRoleGroup::getId, id)
                .eq(AgentRoleGroup::getUserId, userId);
        List<AgentRoleGroup> agentRoleGroups = baseMapper.selectList(wrapper);
        if (!agentRoleGroups.isEmpty()) {
            throw new GeneralException(HttpStatus.agentUserIdError);
        }
        return true;
    }

    /**
     * 新增组钱包
     *
     * @param pid     父级id
     * @param groupId 组id
     * @return
     */
    private void insertWallet(Integer pid, Integer groupId) {

        PlatformWallet pw = null;
        //当为第一级是pid为0 新增代理组钱包
        if (0 == pid) {
            //先查询是否存在组钱包
            //存在不需要新增
            if (platformWalletMapper.getId(groupId) != null) {
                return;
            }
            pw = new PlatformWallet();
            pw.setAgentRoleGroupId(groupId);
            pw.setCreateTime(TimeUtil.unixTime());
            pw.setMoney(BigDecimal.ZERO);
        }
        if (pw != null) {
            platformWalletMapper.insert(pw);
        }
    }


    /**
     * 递归设置下级
     *
     * @param first   第一层
     * @param userVos 代理人员
     * @return
     */
    private List<AgentRoleGroupVo> setChild(List<AgentRoleGroupVo> first) {
        if (CollectionUtil.isNotEmpty(first)) {
            //获取所有子集组
            List<AgentRoleGroupVo> groupVos = baseMapper.listAgentRoleGroup(first.stream().map(AgentRoleGroupVo::getId).toList());

            if (!groupVos.isEmpty()) {
                //得到管理员ids
                List<Long> userIds = groupVos.stream().map(AgentRoleGroupVo::getUserId).toList();

                List<User> user = userMapper.getUserByIds(userIds);

                Map<Long, User> userMap = user.stream().collect(Collectors.toMap(User::getId, u -> u));

                groupVos.forEach(g -> {
                    if (userMap.containsKey(g.getUserId())) {
                        g.setNickname(userMap.get(g.getUserId()).getNickname());
                        g.setPhone(userMap.get(g.getUserId()).getPhone());
                    }
                });
            }
            //查询平台代理提成组提成信息
            List<Integer> ids = first.stream().map(AgentRoleGroupVo::getId).toList();
            LambdaQueryWrapper<AgentRoleGroupRatio> wrapper = new LambdaQueryWrapper<>();
            wrapper.in(AgentRoleGroupRatio::getAgentRoleGroupId, ids);
            List<AgentRoleGroupRatio> agentRoleGroupRatios = agentRoleGroupRatioMapper.selectList(wrapper);
            Map<Integer, AgentRoleGroupRatio> map = agentRoleGroupRatios.stream().collect(Collectors.toMap(AgentRoleGroupRatio::getAgentRoleGroupId, agentRoleGroupRatio -> agentRoleGroupRatio));

            for (AgentRoleGroupVo groupVo : first) {

                if (map.containsKey(groupVo.getId())) {
                    AgentRoleGroupRatio agent = map.get(groupVo.getId());
                    groupVo.setAgentRoleGroupId(agent.getAgentRoleGroupId());
                    groupVo.setPlatformRatio(agent.getPlatformRatio());
                    groupVo.setCommissionRatio(agent.getCommissionRatio());
                    groupVo.setAgentUserRatioOne(agent.getAgentUserRatioOne());
                    groupVo.setAgentUserRatioTwo(agent.getAgentUserRatioTwo());
                    groupVo.setAgentUserRatio(agent.getAgentUserRatio());
                }

                List<AgentRoleGroupVo> childs = groupVos.stream().filter(r -> r.getPid().equals(groupVo.getId())).toList();
                groupVo.setChildren(setChild(childs));
            }
            return first;
        }
        return Collections.emptyList();
    }
}
